package com.example.mvpframe.provider.alioss;

import android.content.Context;
import android.os.Build;
import android.util.Log;

import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.callback.OSSProgressCallback;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.tchhy.basemodule.common.AliossConfig;
import com.tchhy.basemodule.common.BaseApplication;
import com.tchhy.basemodule.utils.GlideUtils;
import com.tchhy.provider.alioss.FileImageEntity;
import com.tchhy.toast.ToastUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;
import top.zibin.luban.Luban;

public class MyOSSUtils {

    private static MyOSSUtils instance;

    private final String P_ENDPOINT = "http://oss-cn-beijing.aliyuncs.com";//主机地址（OSS文档中有提到）

   

    private OSS oss;

    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
    ;

    private MyOSSUtils() {

    }

    public static MyOSSUtils getInstance() {
        if (instance == null) {
            synchronized (MyOSSUtils.class) {
                if (instance == null) {
                    return new MyOSSUtils();
                }
                return instance;
            }
        }
        return instance;

    }

    private void getOSs(Context context) {
        oss = ((BaseApplication) (context.getApplicationContext())).getOSs();


    }

    /**
     * 上传图片 上传文件
     *
     * @param context       application上下文对象
     * @param ossUpCallback 成功的回调
     * @param img_name      上传到oss后的文件名称，图片要记得带后缀 如：.jpg
     * @param imgPath       图片的本地路径
     */

    public void upImage(Context context, final OssUpCallback ossUpCallback, final String img_name, String imgPath,String formMoudle) {

        getOSs(context);

        final Date data = new Date();

        data.setTime(System.currentTimeMillis());

        PutObjectRequest putObjectRequest = new PutObjectRequest(AliossConfig.BUCKET_NAME, "Android/"+formMoudle+simpleDateFormat.format(data) + "/" + img_name, imgPath);

        putObjectRequest.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {

            @Override
            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {

                ossUpCallback.inProgress(currentSize, totalSize);

            }


        });

        oss.asyncPutObject(putObjectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {

            @Override

            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                ossUpCallback.successImg(oss.presignPublicObjectURL(AliossConfig.BUCKET_NAME, "Android/"+formMoudle+simpleDateFormat.format(data) + "/" + img_name));

            }

            @Override

            public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                ossUpCallback.successImg(null);

            }

        });

    }

    /**
     * 上传图片 上传流
     *
     * @param context       application上下文对象
     * @param ossUpCallback 成功的回调
     * @param img_name      上传到oss后的文件名称，图片要记得带后缀 如：.jpg
     * @param imgbyte       图片的byte数组
     */

    public void upImage(Context context, final OssUpCallback ossUpCallback, final String img_name, byte[] imgbyte,String formMoudle) {

        getOSs(context);

        final Date data = new Date();

        data.setTime(System.currentTimeMillis());

        PutObjectRequest putObjectRequest = new PutObjectRequest(AliossConfig.BUCKET_NAME, "Android/"+formMoudle+simpleDateFormat.format(data) + "/" + img_name, imgbyte);

        putObjectRequest.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {

            @Override

            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {

                ossUpCallback.inProgress(currentSize, totalSize);

            }

        });

        oss.asyncPutObject(putObjectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {

            @Override

            public void onSuccess(PutObjectRequest request, PutObjectResult result) {
                ToastUtils.show(result.toString());
                Log.e("MyOSSUtils", "------getRequestId:" + result.getRequestId());

                ossUpCallback.successImg(result.toString());

            }

            @Override

            public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
                ToastUtils.show(clientException.getMessage());
                ossUpCallback.successImg(null);

            }

        });

    }

    /**
     * 上传视频
     *
     * @param context       application上下文对象
     * @param ossUpCallback 成功的回调
     * @param video_name    上传到oss后的文件名称，视频要记得带后缀 如：.mp4
     * @param video_path    视频的本地路径
     */

    public void upVideo(Context context, final OssUpCallback ossUpCallback, final String video_name, String video_path,String formMoudle) {
        getOSs(context);
        final Date data = new Date();
        data.setTime(System.currentTimeMillis());

        PutObjectRequest putObjectRequest = new PutObjectRequest(AliossConfig.BUCKET_NAME,
                "Android/"+formMoudle+simpleDateFormat.format(data) + "/" + video_name, video_path);

        putObjectRequest.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {

            @Override

            public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {

                ossUpCallback.inProgress(currentSize, totalSize);

            }

        });

        oss.asyncPutObject(putObjectRequest, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {

            @Override

            public void onSuccess(PutObjectRequest request, PutObjectResult result) {

                ossUpCallback.successVideo(oss.presignPublicObjectURL(AliossConfig.BUCKET_NAME, "Android/"+formMoudle+simpleDateFormat.format(data) + "/" + video_name));

            }

            @Override

            public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {

                ossUpCallback.successVideo(null);

            }

        });

    }

    public Observable<PutObjectResult> upImages(Context context, final ArrayList<FileImageEntity> pathList, String formMoudle) {
        getOSs(context);

        int threadNum = Runtime.getRuntime().availableProcessors();

        final ExecutorService executor = Executors.newFixedThreadPool(threadNum);

        return Observable.fromIterable(pathList)
                .filter(new Predicate<FileImageEntity>() {
                    @Override
                    public boolean test(FileImageEntity fileImageEntity) throws Exception {
                        if (fileImageEntity.getSource().startsWith("http")) {
                            fileImageEntity.setTarget(fileImageEntity.getSource());
                            return false;
                        } else {
                            return true;
                        }
                    }
                })
                .flatMap(bean -> Observable.just(bean)
                        .map(upImageBean -> {
                            PutObjectRequest put;
                            String tempPath = "";
                            try {
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                                    File sourceFile = new File(upImageBean.getSource());
                                    tempPath = context.getExternalFilesDir("tempImage").getAbsolutePath()
                                            + File.separator + sourceFile.getName();
                                    File tempFile = new File(tempPath);
                                    InputStream iStream = context.getContentResolver().openInputStream(GlideUtils.INSTANCE.getImageContentUri(context, upImageBean.getSource()));
                                    FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
                                    byte[] buffer = new byte[1024];
                                    int len = -1;
                                    if (iStream != null) {
                                        while ((len = iStream.read(buffer)) != -1) {
                                            fileOutputStream.write(buffer, 0, len);
                                        }
                                    }
                                    iStream.close();
                                    fileOutputStream.close();
                                } else {
                                    tempPath = upImageBean.getSource();
                                }
                                String compressedPath = Luban.with(context).load(tempPath)
                                            .get().get(0).getAbsolutePath();
                                File compressedFile = new File(compressedPath);
                                Log.d("MyTest", "compressedPath=" + compressedPath);
                                if (compressedFile.exists()) {
                                    put = new PutObjectRequest(AliossConfig.BUCKET_NAME, "Android/"+formMoudle+upImageBean.getTarget(), compressedPath);
                                } else {
                                    put = new PutObjectRequest(AliossConfig.BUCKET_NAME, "Android/"+formMoudle+upImageBean.getTarget(), tempPath);
                                }


                                return oss.putObject(put);
                            } catch (ClientException e) {
                                e.printStackTrace();
                            } catch (ServiceException e) {
                                e.printStackTrace();
                            }
                            return null;
                        })
                        .subscribeOn(Schedulers.from(executor)))
                .subscribeOn(Schedulers.io())
                .doFinally(() -> executor.shutdown())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public interface OssUpCallback {

        void successImg(String img_url);

        void successVideo(String video_url);

        void inProgress(long progress, long zong);

    }


    public byte[] getBytes(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];

        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }
        return byteBuffer.toByteArray();
    }

}